package com.github.llyb120.sxmanage;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Cleanup;
import org.apache.tomcat.jni.Proc;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

import static com.github.llyb120.sxmanage.Util.HandleScript;
import static com.github.llyb120.sxmanage.Util.RunScript;
import static com.github.llyb120.sxmanage.WebSocketServer.findByName;
import static com.github.llyb120.sxmanage.WebSocketServer.send;

/**
 * @Author: Administrator
 * @Date: 2020/12/3 13:35
 */
@ServerEndpoint("/log/{name}")
@Component
public class LogServer {

    public static final String PUSH_LOG = "PUSH_LOG";
    public static String clearLogScript;

    static {
        InputStream is = new ClassPathResource("clearDockerLogs.sh").getStream();
        clearLogScript = IoUtil.read(is, StandardCharsets.UTF_8);
        IoUtil.close(is);
    }

    static Map<Session, CountDownLatch> countDownLatchMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "name") String name) {
        String token = session.getRequestParameterMap().get("token").get(0);
        if (token == null) {
            IoUtil.close(session);
            return;
        }
        if(!LoginController.tokens.contains(token)){
            IoUtil.close(session);
            return;
        }
        //向前端直接输出日志
        ServiceConfig.Config config = findByName(name);
        if (StrUtil.isBlank(config.getLog())) {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        ThreadUtil.execute(() -> {
            Process process = null;
//            File file = null;
            try {
//                file = File.createTempFile("test", ".tmp");
                LinkedList<String> script = new LinkedList<>();
                script.add(HandleScript(clearLogScript));
                script.add(config.getLog());
                process = RunScript(String.join("\n", script), true);
//                System.out.println(file.getAbsolutePath());
                Process finalProcess = process;
                ThreadUtil.execute(() -> {
                    streamReader(session, finalProcess.getInputStream());
                });
                ThreadUtil.execute(() -> {
                    streamReader(session, finalProcess.getErrorStream());
                });
                CountDownLatch countDownLatch;
                countDownLatchMap.put(session, countDownLatch = new CountDownLatch(1));
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (process != null) {
                    try {
                        process.destroy();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
//                if (file != null) {
//                    file.delete();
//                }
                System.out.println("end");
            }
        });
    }


    static void streamReader(Session session, InputStream inputStream) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while (true) {
            try {
                line = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
            if (line == null) {
                ThreadUtil.sleep(500);
                continue;
            }
            send(session, PUSH_LOG, line);
        }
        IoUtil.close(reader);
    }


    @OnClose
    public void onClose(Session session) {
        CountDownLatch countDownLatch = countDownLatchMap.remove(session);
        if (countDownLatch != null) {
            countDownLatch.countDown();
        }
    }

}
